﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;

namespace ConsoleHost.Extensions
{
    public class SingleSessionPerUserManager : ServiceAuthorizationManager
    {
        public SingleSessionPerUserManager()
        {
            Storage = new SessionStorage();
        }

        private SessionStorage Storage { get; set; }

        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            string name = operationContext.ServiceSecurityContext.PrimaryIdentity.Name;
            if (Storage.IsAnotherSessionWorks(name, operationContext.SessionId))
                return false;

            Storage.Activate(operationContext.SessionId, name);
            operationContext.Channel.Closed += Channel_Closed;
            return true;
        }

        private void Channel_Closed(object sender, EventArgs e)
        {
            Storage.Deactivate((sender as IContextChannel).SessionId);
        }
    }

    public class SessionStorage
    {
        public SessionStorage()
        {
            Names = new Dictionary<string, string>();
        }

        private Dictionary<string, string> Names { get; set; }

        public void Activate(string sessionId, string name)
        {
            Names[name] = sessionId;
        }

        public void Deactivate(string sessionId)
        {
            string name = (from n in Names where n.Value == sessionId select n.Key).FirstOrDefault();
            if (name == null)
                return;

            Names.Remove(name);
        }

        public bool IsAnotherSessionWorks(string name, string session)
        {
            return Names.ContainsKey(name) && !Names[name].Contains(session);
        }
    }
}